/*
 *  This file is part of WWWPal.
 *
 *  Copyright (C) 2003  Dr. John Punin, Department of Computer Science
 *  Rensselaer Polytechnic Institute
 *
 *  WWWPal is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  WWWPal is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "rep_blinks.h"
#include "rep_general.h"
#include "GR_write_html.h"

void
write_body_pblinks_html_file(GraphFrame *gf,FILE *fp);
void
write_body_objects_html_file(GraphFrame *gf,FILE *fp);
void
write_body_blinks_html_file(GraphFrame *gf,FILE *fp);
void
write_body_ord_pblinks_html_file(GraphFrame *gf,FILE *fp);
void
write_body_ord_blinks_html_file(GraphFrame *gf,FILE *fp);
void
write_body_ord_objects_html_file(GraphFrame *gf,FILE *fp);

int 
report_pages_broken_links(GraphFrame *gf, char *name_file)
{
  FILE *fp = assert_open_html_file(name_file);
  if(!fp)
      return -1;
  write_head_html_file(fp,"Pages with Broken Links");
  write_body_pblinks_html_file(gf,fp);
  write_end_html_file(fp);
  fclose(fp);
  return 0;
}

void
write_body_pblinks_html_file(GraphFrame *gf,FILE *fp)
{

  LNode_type *nodes = get_list_vertices(gf);
  LNode_type *ptr = nodes->back;
  time_t now;
  now = time(NULL);
  write_start_body_html_file(fp,"#ffffff");
  write_header_html_file(fp,1,"List of Pages with Broken Links");
  write_bold_html_file(fp,"Last Update :");
  fprintf(fp, " %s",ctime(&now));
  write_break_html_file(fp);
  write_horizontal_rule_html_file(fp);
  fprintf(fp,RPBLString);
  write_horizontal_rule_html_file(fp);
  write_start_ul_html_file(fp);
  for(; ptr != nodes; ptr=ptr->back)
    {
      struct pt *v = (struct pt *)ptr->info;
      LNode_type *peo, *ledges_out = get_edges_out(v);
      int found = 0;
      for(peo = ledges_out->back ; peo != ledges_out ; peo = peo->back)
	{
	  struct edge *e = (struct edge *)peo->info;
	  struct pt *u = get_to_vertex(e);

	  if(get_edge_attribute(e) == 'z')
	    continue;

	  if(vertex_http_code(u) == 404)
	    {
	      char * sanchor = get_label_edge(e);
	      found++;
	      if(found == 1)
		{
		  const char *att = get_attribute(v,"title");
		  char *la = get_label_vertex(v);
		  write_item_html_file(fp);
		  if(att)
		  {
		    write_start_a_href_html_file(fp,la);
		    fprintf(fp,"%s",att);
		    write_break_html_file(fp);
		    fprintf(fp,"%s",la);
		    write_end_a_href_html_file(fp);
		  }
		  else
		  {
		    write_start_a_href_html_file(fp,la);
		    fprintf(fp,"%s",la);
		    write_end_a_href_html_file(fp);
		  }
		  write_start_ol_html_file(fp);
		}
	      write_item_html_file(fp);

	      if(sanchor)	
	      {
		  write_start_pre_html_file(fp);
		  write_bold_html_file(fp,"Caption:");
		  write_string_html_file(fp,sanchor);
		  fprintf(fp,"\n");
		  write_string_html_file(fp,get_label_vertex(u));
		  write_end_pre_html_file(fp);
	      }
	      else
	      {
		  write_start_pre_html_file(fp);
		  write_string_html_file(fp,get_label_vertex(u));
		  write_end_pre_html_file(fp);
	      }
	    }
	}
      if(found != 0)
	  write_end_ol_html_file(fp);
    }
  write_end_ul_html_file(fp);
  write_end_body_html_file(fp);
}

int 
report_ord_pages_broken_links(GraphFrame *gf, char *name_file)
{
  FILE *fp = assert_open_html_file(name_file);
  if(!fp)
      return -1;
  write_head_html_file(fp,"Pages with Broken Links");
  write_body_ord_pblinks_html_file(gf,fp);
  write_end_html_file(fp);
  fclose(fp);
  return 0;
}

void
write_body_ord_pblinks_html_file(GraphFrame *gf,FILE *fp)
{
  LNode_type *nodes = get_list_vertices(gf);
  LNode_type *ptr = nodes->back;
  time_t now;
  int nbpages = 0;

  PNODE *varray = NULL;
  int i = 0;

  for(; ptr != nodes; ptr=ptr->back)
    {
      PNODE v = (PNODE)ptr->info;
      LNode_type *peo, *ledges_out = get_edges_out(v);
      for(peo = ledges_out->back ; peo != ledges_out ; peo = peo->back)
	{
	  PEDGE e = (PEDGE)peo->info;
	  PNODE u = get_to_vertex(e);

	  if(get_edge_attribute(e) == 'z')
	    continue;

	  if(vertex_http_code(u) == 404)
	    {
	      nbpages++;
	      break;
	    }
	}
    }

  if(nbpages == 0)
  {
    now = time(NULL);
    write_start_body_html_file(fp,"#ffffff");
    write_header_html_file(fp,1,"List of Pages with Broken Links");
    write_bold_html_file(fp,"Last Update :");
    fprintf(fp, " %s",ctime(&now));
    write_break_html_file(fp);
    write_horizontal_rule_html_file(fp);
    fprintf(fp,RPBLString);
    write_horizontal_rule_html_file(fp);
    fprintf(fp, "No Broken Links\n");
    write_end_body_html_file(fp);
    return;
  }

  varray = nbpages ? (PNODE *)calloc(nbpages,sizeof(PNODE)) : NULL;

  if(!varray) {
      fprintf(stderr,"Out of Memory write_body_ord_pblinks_html_file\n");
      abort();
  }
  i=0;
  for(ptr = nodes->back; ptr != nodes; ptr=ptr->back)
    {
      PNODE v = (PNODE)ptr->info;
      LNode_type *peo, *ledges_out = get_edges_out(v);
      for(peo = ledges_out->back ; peo != ledges_out ; peo = peo->back)
	{
	  PEDGE e = (PEDGE)peo->info;
	  PNODE u = get_to_vertex(e);

	  if(get_edge_attribute(e) == 'z')
	    continue;

	  if(vertex_http_code(u) == 404)
	    {
	      varray[i++]=v;
	      break;
	    }
	}
    }

  randomized_quicksort((GPTR *)varray,0,nbpages-1,
		       is_vertex_label_lower,is_vertex_label_bigger);

  now = time(NULL);
  write_start_body_html_file(fp,"#ffffff");
  write_header_html_file(fp,1,"List of Pages with Broken Links");
  write_bold_html_file(fp,"Last Update :");
  fprintf(fp, " %s",ctime(&now));
  write_break_html_file(fp);
  write_horizontal_rule_html_file(fp);
  fprintf(fp,RPBLString);
  write_horizontal_rule_html_file(fp);
  write_start_ul_html_file(fp);

  for(i=0;i<nbpages; i++)
  {
      PNODE v = varray[i];
      LNode_type *peo, *ledges_out = get_edges_out(v);
      int found = 0;
      for(peo = ledges_out->back ; peo != ledges_out ; peo = peo->back)
	{
	  struct edge *e = (struct edge *)peo->info;
	  struct pt *u = get_to_vertex(e);

	  if(get_edge_attribute(e) == 'z')
	    continue;

	  if(vertex_http_code(u) == 404)
	    {
	      char * sanchor = get_label_edge(e);
	      found++;
	      if(found == 1)
		{
		  const char *att = get_attribute(v,"title");
		  char *la = get_label_vertex(v);
		  write_item_html_file(fp);
		  if(att)
		  {
		    write_start_a_href_html_file(fp,la);
		    fprintf(fp,"%s",att);
		    write_break_html_file(fp);
		    fprintf(fp,"%s",la);
		    write_end_a_href_html_file(fp);
		  }
		  else
		  {
		    write_start_a_href_html_file(fp,la);
		    fprintf(fp,"%s",la);
		    write_end_a_href_html_file(fp);
		  }
		  write_start_ol_html_file(fp);
		}
	      write_item_html_file(fp);

	      if(sanchor)	
	      {
		  write_start_pre_html_file(fp);
		  write_bold_html_file(fp,"Caption:");
		  write_string_html_file(fp,sanchor);
		  fprintf(fp,"\n");
		  write_string_html_file(fp,get_label_vertex(u));
		  write_end_pre_html_file(fp);
	      }
	      else
	      {
		  write_start_pre_html_file(fp);
		  write_string_html_file(fp,get_label_vertex(u));
		  write_end_pre_html_file(fp);
	      }
	    }
	}
      if(found != 0)
	  write_end_ol_html_file(fp);
    }
  write_end_ul_html_file(fp);
  write_end_body_html_file(fp);
  free(varray); varray = NULL;
}

int 
report_broken_objects(GraphFrame *gf, char *name_file)
{
  FILE *fp = assert_open_html_file(name_file);
  if(!fp)
      return -1;
  write_head_html_file(fp,"List of Broken Objects");
  write_body_objects_html_file(gf,fp);
  write_end_html_file(fp);
  fclose(fp);
  return 0;
}

void
write_body_objects_html_file(GraphFrame *gf,FILE *fp)
{

  LNode_type *nodesobj = get_list_objects(gf);
  LNode_type *ptr = nodesobj->back;

  time_t now;
  now = time(NULL);
  write_start_body_html_file(fp,"#ffffff");
  write_header_html_file(fp,1,"List of Broken Objects");
  write_bold_html_file(fp,"Last Update :");
  fprintf(fp, " %s",ctime(&now));
  write_break_html_file(fp);
  write_horizontal_rule_html_file(fp);
  fprintf(fp,RLBOString);
  write_horizontal_rule_html_file(fp);
  write_start_ol_html_file(fp);

  for(; ptr != nodesobj; ptr=ptr->back)
    {
      struct pt *v = (struct pt *)ptr->info;
      LNode_type *peo, *ledges_in = get_edges_in(v);

      if(vertex_http_code(v) != 404)
	continue;
      write_item_html_file(fp);
      write_start_pre_html_file(fp);
      write_string_html_file(fp,get_label_vertex(v));
      write_end_pre_html_file(fp);
      write_start_ul_html_file(fp);

      for(peo = ledges_in->back ; peo != ledges_in ; peo = peo->back)
	{
	  struct edge *e = (struct edge *)peo->info;
	  struct pt *u = get_from_vertex(e);

	  const char *att = get_attribute(u,"title");
	  char *la = get_label_vertex(u);
	  write_item_html_file(fp);
	  if(att)
	  {
	    write_start_a_href_html_file(fp,la);
	    fprintf(fp,"%s",att);
	    write_break_html_file(fp);
	    fprintf(fp,"%s",la);
	    write_end_a_href_html_file(fp);
	  }
	  else
	  {
	    write_start_a_href_html_file(fp,la);
	    fprintf(fp,"%s",la);
	    write_end_a_href_html_file(fp);
	  }
	}
      write_end_ul_html_file(fp);
    }
  write_end_ol_html_file(fp);
  write_end_body_html_file(fp);
}

int 
report_ord_broken_objects(GraphFrame *gf, char *name_file)
{
  FILE *fp = assert_open_html_file(name_file);
  if(!fp)
      return -1;
  write_head_html_file(fp,"List of Broken Objects");
  write_body_ord_objects_html_file(gf,fp);
  write_end_html_file(fp);
  fclose(fp);
  return 0;
}

void
write_body_ord_objects_html_file(GraphFrame *gf,FILE *fp)
{

  LNode_type *nodesobj = get_list_objects(gf);
  LNode_type *ptr = NULL;
  int nbobj = 0;
  PNODE *varray = NULL;
  time_t now;
  int i = 0;

  now = time(NULL);
  write_start_body_html_file(fp,"#ffffff");
  write_header_html_file(fp,1,"List of Broken Objects");
  write_bold_html_file(fp,"Last Update :");
  fprintf(fp, " %s",ctime(&now));
  write_break_html_file(fp);
  write_horizontal_rule_html_file(fp);
  fprintf(fp,RLBOString);
  write_horizontal_rule_html_file(fp);

  for(ptr = nodesobj->back; ptr != nodesobj; ptr=ptr->back)
    {
      PNODE v = (PNODE)ptr->info;

      if(vertex_http_code(v) == 404)
	  nbobj++;

    }

  if(nbobj == 0)
  {
    fprintf(fp, "No Broken Objects\n");
    write_end_body_html_file(fp);
    return;
  }
   
  varray = nbobj ? (PNODE *)calloc(nbobj,sizeof(PNODE)) : NULL;

  if(!varray) {
      fprintf(stderr,"Out of Memory write_body_ord_objects_html_file\n");
      abort();
  }

  i=0;
  for(ptr = nodesobj->back; ptr != nodesobj; ptr=ptr->back)
    {
      PNODE v = (PNODE)ptr->info;

      if(vertex_http_code(v) == 404)
	varray[i++]=v;
    }

  randomized_quicksort((GPTR *)varray,0,nbobj-1,
		       is_vertex_label_lower,is_vertex_label_bigger);

  write_start_ol_html_file(fp);

  for(i=0;i<nbobj; i++)
    {
      PNODE v = varray[i];
      LNode_type *peo, *ledges_in = get_edges_in(v);

      write_item_html_file(fp);
      write_start_pre_html_file(fp);
      write_string_html_file(fp, get_label_vertex(v));
      write_end_pre_html_file(fp);
      write_start_ul_html_file(fp);

      for(peo = ledges_in->back ; peo != ledges_in ; peo = peo->back)
	{
	  struct edge *e = (struct edge *)peo->info;
	  struct pt *u = get_from_vertex(e);

	  const char *att = get_attribute(u,"title");
	  char *la = get_label_vertex(u);
	  write_item_html_file(fp);
	  if(att)
	  {
	    write_start_a_href_html_file(fp,la);
	    fprintf(fp,"%s",att);
	    write_break_html_file(fp);
	    fprintf(fp,"%s",la);
	    write_end_a_href_html_file(fp);
	  }
	  else
	  {
	    write_start_a_href_html_file(fp,la);
	    fprintf(fp,"%s",la);
	    write_end_a_href_html_file(fp);
	  }
	}
      write_end_ul_html_file(fp);
    }
  write_end_ol_html_file(fp);
  write_end_body_html_file(fp);
  free(varray); varray = NULL;
}

int 
report_broken_links(GraphFrame *gf, char *name_file)
{
  FILE *fp = assert_open_html_file(name_file);
  if(!fp)
      return -1;
  write_head_html_file(fp,"Broken Links");
  write_body_blinks_html_file(gf,fp);
  write_end_html_file(fp);
  fclose(fp);
  return 0;
}

void
write_body_blinks_html_file(GraphFrame *gf,FILE *fp)
{
  LNode_type *nodes = get_list_vertices(gf);
  LNode_type *ptr = nodes->back;
  time_t now;
  now = time(NULL);
  write_start_body_html_file(fp,"#ffffff");
  write_header_html_file(fp,1,"List of Broken Links");
  write_bold_html_file(fp,"Last Update :");
  fprintf(fp, " %s",ctime(&now));
  write_break_html_file(fp);
  write_horizontal_rule_html_file(fp);
  fprintf(fp,RLBLString);
  write_horizontal_rule_html_file(fp);
  write_start_ol_html_file(fp);

  for(; ptr != nodes; ptr=ptr->back)
    {
      PNODE v = (PNODE)ptr->info;
      LNode_type *pei = NULL, *ledges_in = NULL; 

      if(vertex_http_code(v) != 404)
	  continue;

      ledges_in = get_edges_in(v);

      write_item_html_file(fp);
      write_start_pre_html_file(fp);
      write_string_html_file(fp,get_label_vertex(v));
      write_end_pre_html_file(fp);
      write_start_ul_html_file(fp);

      for(pei = ledges_in->back ; pei != ledges_in ; pei = pei->back)
	{
	  PEDGE e = (PEDGE)pei->info;
	  PNODE u = get_from_vertex(e);

	  if(get_edge_attribute(e) == 'z')
	    continue;

	  {
	    char *sanchor = get_label_edge(e);
	    const char *att = get_attribute(u,"title");
	    char *la = get_label_vertex(u);

	    write_item_html_file(fp);
	    if(sanchor)	
	    {
	      write_start_pre_html_file(fp);
	      write_bold_html_file(fp,"Caption:");
	      write_string_html_file(fp,sanchor);
	      write_end_pre_html_file(fp);
	    }
	    if(att)
	    {
	      write_start_a_href_html_file(fp,la);
	      fprintf(fp,"%s",att);
	      write_break_html_file(fp);
	      fprintf(fp,"%s",la);
	      write_end_a_href_html_file(fp);
	    }
	    else
	    {
	      write_start_a_href_html_file(fp,la);
	      fprintf(fp,"%s",la);
	      write_end_a_href_html_file(fp);
	    }

	  }
	}
      write_end_ul_html_file(fp);	
    }
  write_end_ol_html_file(fp);
  write_end_body_html_file(fp);
}

int 
report_ord_broken_links(GraphFrame *gf, char *name_file)
{
  FILE *fp = assert_open_html_file(name_file);
  if(!fp)
      return -1;
  write_head_html_file(fp,"Broken Links");
  write_body_ord_blinks_html_file(gf,fp);
  write_end_html_file(fp);
  fclose(fp);
  return 0;
}

void
write_body_ord_blinks_html_file(GraphFrame *gf,FILE *fp)
{
  LNode_type *nodes = get_list_vertices(gf);
  LNode_type *ptr = nodes->back;
  time_t now;

  int nbpages = 0;

  PNODE *varray = NULL;
  int i = 0;

  for(; ptr != nodes; ptr=ptr->back)
    {
      PNODE v = (PNODE)ptr->info;
      if(vertex_http_code(v) == 404 && !is_vertex_object(v))
	nbpages++;
    }

  if(nbpages == 0)
  {
    now = time(NULL);
    write_start_body_html_file(fp,"#ffffff");
    write_header_html_file(fp,1,"List of Broken Links");
    write_bold_html_file(fp,"Last Update :");
    fprintf(fp, " %s",ctime(&now));
    write_break_html_file(fp);
    write_horizontal_rule_html_file(fp);
    fprintf(fp,RLBLString);
    write_horizontal_rule_html_file(fp);
    fprintf(fp, "No Broken Links\n");
    write_end_body_html_file(fp);
    return;
  }

  varray = nbpages ? (PNODE *)calloc(nbpages,sizeof(PNODE)) : NULL;

  if(!varray) {
      fprintf(stderr,"Out of Memory write_body_ord_blinks_html_file\n");
      abort();
  }

  i=0;
  for(ptr = nodes->back; ptr != nodes; ptr=ptr->back)
    {
      PNODE v = (PNODE)ptr->info;
      if(vertex_http_code(v) == 404 && !is_vertex_object(v))
	  varray[i++]=v;
    }

  randomized_quicksort((GPTR *)varray,0,nbpages-1,
		       is_vertex_label_lower,is_vertex_label_bigger);


  now = time(NULL);
  write_start_body_html_file(fp,"#ffffff");
  write_header_html_file(fp,1,"List of Broken Links");
  write_bold_html_file(fp,"Last Update :");
  fprintf(fp, " %s",ctime(&now));
  write_break_html_file(fp);
  write_horizontal_rule_html_file(fp);
  fprintf(fp,RLBLString);
  write_horizontal_rule_html_file(fp);
  write_start_ol_html_file(fp);

  for(i=0;i<nbpages; i++)
  {
      PNODE v = varray[i];
      LNode_type *pei = NULL, *ledges_in = NULL; 

      ledges_in = get_edges_in(v);

      write_item_html_file(fp);
      write_start_pre_html_file(fp);
      write_string_html_file(fp,get_label_vertex(v));
      write_end_pre_html_file(fp);
      write_start_ul_html_file(fp);

      for(pei = ledges_in->back ; pei != ledges_in ; pei = pei->back)
	{
	  PEDGE e = (PEDGE)pei->info;
	  PNODE u = get_from_vertex(e);

	  if(get_edge_attribute(e) == 'z')
	    continue;

	  {
	    char *sanchor = get_label_edge(e);
	    const char *att = get_attribute(u,"title");
	    char *la = get_label_vertex(u);

	    write_item_html_file(fp);
	    if(sanchor)	
	    {
	      write_start_pre_html_file(fp);
	      write_bold_html_file(fp,"Caption:");
	      write_string_html_file(fp,sanchor);
	      write_end_pre_html_file(fp);
	    }
	    if(att)
	    {
	      write_start_a_href_html_file(fp,la);
	      fprintf(fp,"%s",att);
	      write_break_html_file(fp);
	      fprintf(fp,"%s",la);
	      write_end_a_href_html_file(fp);
	    }
	    else
	    {
	      write_start_a_href_html_file(fp,la);
	      fprintf(fp,"%s",la);
	      write_end_a_href_html_file(fp);
	    }

	  }
	}
      write_end_ul_html_file(fp);	
    }
  write_end_ol_html_file(fp);
  write_end_body_html_file(fp);
  free(varray); varray = NULL;
}

